/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_comm.c                                         */
/*  NOTE      =                                                    */
/*  DATE      = 2014/10/09 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include "frdb_cursor.h"

#include "frcomm.h"
#include "frstr.h"
#include "frmem.h"
#include "frhash2.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"
#include "frreport_comm.h"
#include "frservice_comm.h"

#include "ora_comm.h"
#include "ora_util.h"
#include "../ora_core.h"
#include "../config.h"

extern void *g_p_apm_context;

/*******************************************************************************
*  FUNC     :  根据limit的长度检查要分配的内存
*  ARGS     :  pp_buffer
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void* __ora_malloc(size_t s_size
                , int i_limit)
{
    if (s_size <= 0 ||
            (i_limit != 0L && s_size > APM_ORA_MEM_MAX_SIZE && s_size > (size_t) i_limit))
    {
        ORA_PRINT_CRIT("ora malloc s_size of %ld is larger than limit of %d\n", s_size, i_limit);
        return NULL;
    }

    return frmalloc(s_size);
}

/*******************************************************************************
*  FUNC     :  释放内存
*  ARGS     :  pp_buffer
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void ora_free(void **pp_buffer)
{
    if (pp_buffer == NULL || *pp_buffer == NULL)
        return;

    frfree(*pp_buffer);
    *pp_buffer = NULL;
    return;
}

/*******************************************************************************
*  FUNC     :  删除左第一个括号
*  ARGS     :  *p_data     (字符串)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __ltrim_parenthesis(char **pp_data)
{
    if (pp_data == NULL || *pp_data == NULL)
        return;
    
    if (**pp_data == '(')
    {
        (*pp_data)++;
    }
    return;
}

/*******************************************************************************
*  FUNC     :  删除右第一个括号
*  ARGS     :  *p_data     (字符串)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __rtrim_parenthesis(char *p_data)
{
    int i = 0;
    int i_found_flag = 0;

    if (p_data == NULL)
        return;

    i = strlen(p_data) - 1;
    while (p_data[i] == ')' && i >= 0 && i_found_flag == 0)
    {
        i--;
        i_found_flag = 1;
    };
    p_data[i + 1] = '\0';
}

/*******************************************************************************
*  FUNC     :  删除左右第一个括号
*  ARGS     :  *p_data     (字符串)
*  RTN      :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __trim_parenthesis(char **pp_data)
{
    if (pp_data == NULL || *pp_data == NULL)
        return;
    
    __ltrim_parenthesis(pp_data);
    __rtrim_parenthesis(*pp_data);
}

/*******************************************************************************
*  FUNC     :  查找最外层第一个配对的左右括号的位置
*  ARGS     :  *p_data     (输入的数据)
*           :  **pp_pair_str      (解析后的数据)
*           :  *pi_pair_str_len      (解析后的数据长度)
*  RTN      :  0       (FR_SUCC)
*              1       (FR_FAIL)
*  NOTE     : 需要外部释放**pp_pair_str的内存
*******************************************************************************/
FR_STATIC int __find_pair_str(char *p_data
                        , char **pp_pair_str
                        , int *pi_pair_str_len)
{
    int i_pair_count = 0;
    int i_data_len = 0;
    int i = 0;
    char *p_left_pos = NULL;
    char *p_pair_str = NULL;

    if (p_data == NULL)
    {
        ORA_PRINT_EMERG("invalid parameter.\n");
        ORA_FRLOG_ERROR("invalid parameter.");
        goto error;
    }
    i_data_len = strlen(p_data);

    for (i = 0; i < i_data_len; i++)
    {
        if (p_data[i] == '\0')
        {
            goto error;
        }
        else if (p_data[i] == '(')
        {
            if (p_left_pos == NULL)
            {
                p_left_pos = p_data + i;
            }
            i_pair_count++;
        }
        else if (p_data[i] == ')')
        {
            i_pair_count--;
            if (i_pair_count == 0)
            {
                if (p_left_pos == NULL)
                {
                    goto error;
                }
                *pi_pair_str_len = strlen(p_left_pos) - strlen(p_data + i) + 1;
                if ((p_pair_str = (char *) frmalloc(*pi_pair_str_len + 1)) == NULL)
                {
                    ORA_MALLOCK_ERR;
                    goto error;
                }

                memcpy(p_pair_str, p_left_pos, *pi_pair_str_len);
                p_pair_str[*pi_pair_str_len] = '\0';
                *pp_pair_str = p_pair_str;

                goto success;
            }
        }
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析节点的key值
*  ARGS     :  *p_data     (输入的数据)
*           :  **pp_key      (解析后的key)
*  RTN      :  0       (FR_SUCC)
*              1       (FR_FAIL)
*  NOTE     : 需要外部释放**pp_key的内存
*******************************************************************************/
FR_STATIC int __parse_key(char *p_data
                    , char **pp_key)
{
    char *p_pos_assignment = NULL;
    char *p_key = NULL;
    int i_key_len;

    if (p_data == NULL)
    {
        ORA_PRINT_EMERG("invalid parameter.\n");
        ORA_FRLOG_ERROR("invalid parameter.");
        goto error;
    }

    p_pos_assignment = strchr(p_data, '=');
    if (NULL != p_pos_assignment)
    {
        i_key_len = p_pos_assignment - p_data;

        p_key = (char *) frmemdup(p_data, i_key_len + 1);
        if (NULL == p_key)
        {
            goto error;
        }
        p_key[i_key_len] = '\0';

        frtrim(p_key);
        *pp_key = p_key;
    }
    else
    {
        ORA_PRINT_EMERG("can not find assignment in child\n");
        ORA_FRLOG_ERROR("can not find assignment in child.");
        goto error;
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析节点的value值
*  ARGS     :  *p_data     (输入的数据)
*           :  **pp_value      (解析后的value)
*  RTN      :  0       (FR_SUCC)
*              1       (FR_FAIL)
*  NOTE     : 需要外部释放**pp_value的内存
*******************************************************************************/
FR_STATIC int __parse_value(char *p_data, char **pp_value)
{
    char *p_pos_assignment = NULL;
    char *p_value = NULL;

    if (p_data == NULL)
    {
        ORA_PRINT_EMERG("invalid parameter.\n");
        ORA_FRLOG_ERROR("invalid parameter.");
        goto error;
    }

    p_pos_assignment = strchr(p_data, '=');
    if (NULL != p_pos_assignment)
    {
        p_value = frstrdup(p_pos_assignment + 1);
        if (NULL == p_value)
        {
            goto error;
        }

        frtrim(p_value);
        *pp_value = p_value;
    }
    else
    {
        ORA_PRINT_EMERG("can not find assignment in child\n");
        ORA_FRLOG_ERROR("can not find assignment in child.");
        goto error;
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  解析节点的value值
*  ARGS     :  *p_data     (输入的数据)
*  RTN      :  0       (FR_SUCC)
*              1       (FR_FAIL)
*  NOTE     :
*******************************************************************************/
FR_STATIC int __is_surround_by_parenthesis(char *p_data)
{
    if (p_data == NULL)
    {
        ORA_PRINT_EMERG("invalid parameter.\n");
        ORA_FRLOG_ERROR("invalid parameter.");
        goto error;
    }

    if (*p_data != '(' || *(p_data + strlen(p_data) - 1) != ')')
    {
        goto error;
    }

    return FR_SUCC;
error:
    return FR_FAIL;
}

//比较一致返回0，其他返回1
FR_STATIC int __list_node_find(Frlist_node *p_st_node
                            , const void *p_compare_data)
{
    if(!p_compare_data)
        return 1;

    return strcmp((char *)p_compare_data, ((Ora_NVPair *)(p_st_node->data))->key);
}

/*******************************************************************************
*  FUNC     :  根据键获取叶子节点的值
*  ARGS     :  *p_st_head  (Frlist_header对象)
*           :  *p_keys      (键，输入格式每个键名用点分隔，例如 DESCRIPTION.CONNECT_DATA.SID )
*           :  **pp_value    (值，例如 orcl )
*  RTN      :  0       (FR_SUCC)
*              1       (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_NVPair_get_value(Frlist_header *p_st_head
                        , const char *p_keys
                        , char **pp_value)
{
    Frlist_node *p_st_node = NULL;
    Ora_NVPair *nvpair = NULL;

    if (p_st_head == NULL)
    {
        ORA_PRINT_EMERG("invalid parameter.\n");
        ORA_FRLOG_ERROR("invalid parameter.");
        goto error;
    }

    p_st_node = frlist_find(p_st_head, p_keys, __list_node_find);
    if (!p_st_node)
        goto error;

    nvpair = (Ora_NVPair *) FRLIST_GET_NODE_DATA(p_st_node);
    if (nvpair != NULL && nvpair->value != NULL)
        *pp_value = nvpair->value;
    else
        goto error;

    return FR_SUCC;
error:
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  拆解connect,redirect包中最后部分的data字符串
*  ARGS     :  *p_data     (实际要解析的数据)
*           :  ui_len      (数据长度)
*           :  *p_st_head_NVPair      (解析完成的数据)
*  RTN      :  0       (FR_SUCC)
*              1       (FR_FAIL)
*  NOTE     : 需要通过ora_NVPair_list_node_free释放p_st_head的内存
*******************************************************************************/
int ora_NVPair_parser(char *p_data
                    , unsigned int ui_len
                    , Frlist_header *p_st_head
                    , Frstr *p_ancestor_keys)
{
    char *p_curr_key = NULL;  // 当前节点的key，例如 SID
    Frstr *p_curr_keys = NULL; // 当前节点的key加上祖先的keys，例如 DESCRIPTION.CONNECT_DATA.SID
    int i_curr_keys_len = 0;
    char *p_curr_value = NULL; // 当前节点的value
    int i_curr_value_len = 0;
    int i_func_ret = 0;
    char *p_child_str = NULL;
    int i_find_pair_str_ret = 0;
    int i_pair_str_len = 0;
    int i_pair_str_total_len = 0;
    Ora_NVPair *p_st_NVPair = NULL;
    Frlist_node *p_st_node = NULL;

    if (p_data == NULL || ui_len == 0)
    {
        ORA_PRINT_EMERG("invalid parameter.\n");
        ORA_FRLOG_ERROR("invalid parameter.");
        goto error;
    }

    frtrim(p_data);
    __trim_parenthesis(&p_data);
    frtrim(p_data);             // 如 DESCRIPTION=(CONNECT_DATA=(SID=orcl)(CID=(PROGRAM=)(HOST=__jdbc__)(USER=)))(ADDRESS=(PROTOCOL=tcp)(HOST=172.16.0.74)(PORT=1521))

    i_func_ret = __parse_key(p_data, &p_curr_key); // p_curr_key的值如 DESCRIPTION
    if (i_func_ret != 0)
        goto error;

    if (p_ancestor_keys != NULL)
    {
        i_curr_keys_len = p_ancestor_keys->ui_len + strlen(p_curr_key) + 1;
        p_curr_keys = frstr_new(i_curr_keys_len + 1);
        frstr_append(p_curr_keys, p_ancestor_keys->p_str, p_ancestor_keys->ui_len);
        frstr_append(p_curr_keys, ".", 1);
        frstr_append(p_curr_keys, p_curr_key, strlen(p_curr_key));
    }
    else
    {
        i_curr_keys_len = strlen(p_curr_key);
        p_curr_keys = frstr_new(i_curr_keys_len + 1);
        frstr_append(p_curr_keys, p_curr_key, i_curr_keys_len);
    }

    i_func_ret = __parse_value(p_data, &p_curr_value); // p_curr_value的值如 (PROGRAM=)(HOST=__jdbc__)(USER=) 或者 __jdbc__
    if (i_func_ret != 0)
        goto error;

    i_func_ret = __is_surround_by_parenthesis(p_curr_value);

    if (i_func_ret == 0) // 存在子节点
    {
        i_curr_value_len = strlen(p_curr_value);

        // 循环查找各个子节点
        while ((i_find_pair_str_ret = __find_pair_str(&p_curr_value[i_pair_str_total_len], &p_child_str, &i_pair_str_len)) == 0)
        {
            i_pair_str_total_len += i_pair_str_len;

            // 迭代解析子节点
            ora_NVPair_parser(p_child_str, i_pair_str_len, p_st_head, p_curr_keys);
            ora_free((void **) &p_child_str);

            if (i_pair_str_total_len >= i_curr_value_len)
            {
                break;
            }
        }
    }
    else // 直接是值
    {
        if ((p_st_NVPair = (Ora_NVPair *) frmalloc(sizeof(Ora_NVPair))) == NULL)
        {
            ORA_MALLOCK_ERR;
            goto error;
        }
        memset(p_st_NVPair, 0x00, sizeof(Ora_NVPair));

        p_st_NVPair->key = frstrdup(p_curr_keys->p_str);
        p_st_NVPair->value = frstrdup(p_curr_value);

        p_st_node = frlist_node_create(p_st_NVPair);

        frlist_push(p_st_head, p_st_node);
    }

    ora_free((void **) &p_curr_key);
    ora_free((void **) &p_curr_value);
    if (p_curr_keys != NULL)
    {
        frstr_free(&p_curr_keys);
    }
    return FR_SUCC;
error:
    ora_free((void **) &p_curr_key);
    ora_free((void **) &p_curr_value);
    if (p_curr_keys != NULL)
    {
        frstr_free(&p_curr_keys);
    }
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  释放NVPair list内存
*  ARGS     :  *node  (Frlist_node对象)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_NVPair_list_node_free(Frlist_node *p_st_node)
{
    if (p_st_node == NULL)
    {
        ORA_PRINT_EMERG("invalid parameter.\n");
        ORA_FRLOG_ERROR("invalid parameter.");
        return;
    }

    Ora_NVPair *nvpair = (Ora_NVPair *) FRLIST_GET_NODE_DATA(p_st_node);

    ora_free((void **) &(nvpair->key));
    ora_free((void **) &(nvpair->value));
    ora_free(&(p_st_node->data));

    return;
}

/*******************************************************************************
*  FUNC     :  设置 arr_ttc_type_rep 的值
*  ARGS     :  *p_st_sess  (L7session_oracle结构体)
*           :  i_location      (位置)
*           :  i_value      (值)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_set_ttc_type_rep(L7session_ora *p_st_sess
                        , int i_location
                        , int i_value)
{
    p_st_sess->arr_ttc_type_rep[i_location] = i_value;
    ORA_PRINT_CRIT("set ttc type rep %d = %d\n", i_location, i_value);
    return;
}

/*******************************************************************************
*  FUNC     :  获取 arr_ttc_type_rep 的值
*  ARGS     :  *p_st_sess  (L7session_oracle结构体)
*           :  i_location      (位置)
*  RTN      :  int
*  NOTE     :
*******************************************************************************/
int ora_get_ttc_type_rep(L7session_ora *p_st_sess
                        , int i_location)
{
    return p_st_sess->arr_ttc_type_rep[i_location];
}

/*******************************************************************************
*  FUNC     :  重置arr_ttc_type_rep 的值为初始化状态
*  ARGS     :  *p_st_sess  (L7session_oracle结构体)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_unset_ttc_type_rep(L7session_ora *p_st_sess)
{
    ORA_PRINT_CRIT("ora_unset_ttc_type_rep\n");
    int i_loop;

     for (i_loop = 0; i_loop < 5; i_loop++)
        ora_set_ttc_type_rep(p_st_sess, i_loop, APM_ORA_FLAG_UNSET);

    return;
}


/*******************************************************************************
*  FUNC     :  设置arr_ttc_type_rep 的值为jdbc方式
*  ARGS     :  *p_st_sess  (L7session_oracle结构体)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_set_ttc_type_rep_jdbc(L7session_ora *p_st_sess)
{
    ORA_PRINT_CRIT("ora_set_ttc_type_rep_jdbc\n");
    int i_loop;

    ora_set_ttc_type_rep(p_st_sess, 0, 0);
    for (i_loop = 1; i_loop < 5; i_loop++)
        ora_set_ttc_type_rep(p_st_sess, i_loop, 1);

    return;
}

/*******************************************************************************
*  FUNC     :  设置Oracle会话过程标识
*  ARGS     :  *p_st_sess  (L7session_oracle结构体)
*           :  em_sess_phase (标识)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_push_sess_phase(Ora_sess_phase arr_sess_phase[APM_ORA_SESS_PHASE_MAX]
                        , Ora_sess_phase em_sess_phase)
{
    int i_loop;
    for (i_loop = 0; i_loop < APM_ORA_SESS_PHASE_MAX; i_loop++)
    {
        if (arr_sess_phase[i_loop] == APM_ORA_SESS_PHASE_INIT)
        {
            if (i_loop > 0)
            {
                if (arr_sess_phase[i_loop - 1] == APM_ORA_SESS_PHASE_OCLOSE8)
                    arr_sess_phase[i_loop - 1] = em_sess_phase;
                else
                    arr_sess_phase[i_loop] = em_sess_phase;
            }
            else
                arr_sess_phase[i_loop] = em_sess_phase;
            ORA_PRINT_INFO("push phase:[%d]\n", em_sess_phase);
            break;
        }
    }
}

/*******************************************************************************
*  FUNC     :  设置最后一个的Oracle会话过程标识
*  ARGS     :  arr_sess_phase  (L7session_oracle结构体数组)
*           :  em_sess_phase   (标识)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_set_last_sess_phase(Ora_sess_phase arr_sess_phase[APM_ORA_SESS_PHASE_MAX]
                            , Ora_sess_phase em_sess_phase)
{
    int i_loop;
    for (i_loop = 0; i_loop < APM_ORA_SESS_PHASE_MAX; i_loop++)
    {
        if (i_loop + 1 < APM_ORA_SESS_PHASE_MAX && arr_sess_phase[i_loop + 1] == APM_ORA_SESS_PHASE_INIT)
        {
            arr_sess_phase[i_loop] = em_sess_phase;
            ORA_PRINT_INFO("set phase:[%d]\n", em_sess_phase);
            break;
        }
    }
    return;
}

/*******************************************************************************
*  FUNC     :  获取Oracle会话过程标识
*  ARGS     :  arr_sess_phase  (L7session_oracle结构体数组)
*  RTN      :
*  NOTE     :
*******************************************************************************/
Ora_sess_phase ora_pop_sess_phase(Ora_sess_phase arr_sess_phase[APM_ORA_SESS_PHASE_MAX])
{
    int i_loop;
    Ora_sess_phase curr_phase = APM_ORA_SESS_PHASE_INIT;
    for (i_loop = 0; i_loop < APM_ORA_SESS_PHASE_MAX; i_loop++)
    {
        if (i_loop == 0)
            curr_phase = arr_sess_phase[i_loop];

        if (i_loop + 1 == APM_ORA_SESS_PHASE_MAX)
        {
            arr_sess_phase[i_loop] = APM_ORA_SESS_PHASE_INIT;
            break;
        }

        if (arr_sess_phase[i_loop + 1] != APM_ORA_SESS_PHASE_INIT)
            arr_sess_phase[i_loop] = arr_sess_phase[i_loop + 1];
        else
        {
            arr_sess_phase[i_loop] = APM_ORA_SESS_PHASE_INIT;
            break;
        }
    }
    if (curr_phase != APM_ORA_SESS_PHASE_INIT)
        ORA_PRINT_INFO("pop phase:[%d]\n", curr_phase);
    return curr_phase;
}

/*******************************************************************************
*  FUNC     :  判断是否是空的会话过程
*  ARGS     :  arr_sess_phase  (L7session_oracle结构体数组)
*  RTN      :
*  NOTE     :
*******************************************************************************/
int ora_is_sess_phase_null(Ora_sess_phase arr_sess_phase[APM_ORA_SESS_PHASE_MAX])
{
    return arr_sess_phase[0] == APM_ORA_SESS_PHASE_INIT ? FR_YES : FR_NO;
}

/*******************************************************************************
*  FUNC     :  重置Oracle会话过程标识
*  ARGS     :  arr_sess_phase  (L7session_oracle结构体数组)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_reset_sess_phase(Ora_sess_phase arr_sess_phase[APM_ORA_SESS_PHASE_MAX])
{
    memset(arr_sess_phase, APM_ORA_SESS_PHASE_INIT, APM_ORA_SESS_PHASE_MAX);
    return;
}

/*******************************************************************************
*  FUNC     :  添加Oracle会话过程标识到另一个数组中去
*  ARGS     :  arr_src_sess_phase  (L7session_oracle结构体数组源)
*           :  arr_dest_sess_phase  (L7session_oracle结构体数组目的)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_add_sess_phase(Ora_sess_phase arr_src_sess_phase[APM_ORA_SESS_PHASE_MAX]
                        , Ora_sess_phase arr_dest_sess_phase[APM_ORA_SESS_PHASE_MAX])
{
    ORA_PRINT_INFO("transfer sess phase\n");
    int i_loop;
    for (i_loop = 0; i_loop < APM_ORA_SESS_PHASE_MAX; i_loop++)
    {
        if (arr_src_sess_phase[i_loop] == APM_ORA_SESS_PHASE_INIT)
            break;
        ora_push_sess_phase(arr_dest_sess_phase, arr_src_sess_phase[i_loop]);
    }
    return;
}

/*******************************************************************************
*  FUNC     :  拷贝Oracle会话过程标识
*  ARGS     :  arr_src_sess_phase  (L7session_oracle结构体数组源)
*           :  arr_dest_sess_phase  (L7session_oracle结构体数组目的)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_copy_sess_phase(Ora_sess_phase arr_src_sess_phase[APM_ORA_SESS_PHASE_MAX]
                         , Ora_sess_phase arr_dest_sess_phase[APM_ORA_SESS_PHASE_MAX])
{
    int i_loop;
    for (i_loop = 0; i_loop < APM_ORA_SESS_PHASE_MAX; i_loop++)
        arr_dest_sess_phase[i_loop] = arr_src_sess_phase[i_loop];
    return;
}

void ora_remaining_last_sess_phase(Ora_sess_phase arr_sess_phase[APM_ORA_SESS_PHASE_MAX])
{
    Ora_sess_phase em_curr_sess_phase;
    Ora_sess_phase last_sess_phase = APM_ORA_SESS_PHASE_INIT;

    while ((em_curr_sess_phase = ora_pop_sess_phase(arr_sess_phase)) != APM_ORA_SESS_PHASE_INIT)
        last_sess_phase = em_curr_sess_phase;

    if (last_sess_phase != APM_ORA_SESS_PHASE_INIT)
        ora_push_sess_phase(arr_sess_phase, last_sess_phase);

    return;
}

int ora_has_svr_compile_time_capability(L7session_ora *p_st_sess
                                        , int i_len
                                        , int i_value)
{
    if (p_st_sess->p_srv_compile_time_capabilities == NULL || p_st_sess->s_srv_compile_time_capabilities_len == 0)
        return APM_ORA_FLAG_UNSET;

    if (p_st_sess->p_srv_compile_time_capabilities != NULL &&
            p_st_sess->s_srv_compile_time_capabilities_len > i_len &&
            (p_st_sess->p_srv_compile_time_capabilities[i_len] & i_value) != 0)
        return FR_SUCC;
    else
        return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  重置private_session中L7_resp_oracle的信息
*  ARGS     :  *p_st_resp               (response信息)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_reset_resp_info(L7_resp_ora *p_st_resp)
{
    p_st_resp->l_response_code = APM_ORA_FLAG_UNSET;
    ora_free((void **) &(p_st_resp->p_response_codestring));
    ora_free((void **) &(p_st_resp->p_response_error_mesg));
    return;
}

/*******************************************************************************
*  FUNC     :  设置large sdu标志
*  ARGS     :  *p_st_sess                              (Oracle私有session)
*           :  i_is_large_sdu                        (large sdu标志)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_sess_set_large_sdu_flag(L7session_ora *p_st_sess
                                , int i_large_sdu_flag)
{
    if (i_large_sdu_flag == APM_ORA_FLAG_UNSET)
        return;
    if (p_st_sess->i_is_large_sdu == FR_YES && i_large_sdu_flag == FR_NO)
    {
        ORA_PRINT_EMERG("i_is_large_sdu setting now:[0] is different from old:[1].\n");
        ORA_FRLOG_ERROR("i_is_large_sdu setting now:[0] is different from old:[1].");
    }
    else
        p_st_sess->i_is_large_sdu = i_large_sdu_flag;
}

/*******************************************************************************
*  FUNC     :
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*  RTN      :  (Frreport_body_data *)
*  NOTE     :
*******************************************************************************/
FR_STATIC Frreport_body_data* __ora_new_report_body(Conntrack *p_st_conn
                                                    , L7session_ora *p_st_sess)
{
    Frreport_body_data *p_st_body = NULL;

    /* 创建report body */
    if ((p_st_body = frreport_body_new_l7(p_st_conn)) == NULL)
        return NULL;

    /* 追加connection相关信息 */
    if ((frreport_body_l7_add_connInfo(p_st_body, p_st_conn)) != FR_SUCC)
        goto error;

    if (p_st_sess->p_username && frreport_body_l7_add_str(p_st_body, APM_REPORT_KEY_SESSION_USERNAME, p_st_sess->p_username) != FR_SUCC)
        goto error;
    if (p_st_sess->p_program && frreport_body_l7_add_str(p_st_body, APM_ORA_REPORT_SESSION_PROGRAM, p_st_sess->p_program) != FR_SUCC)
        goto error;
    if (p_st_sess->p_db_sid && frreport_body_l7_add_str(p_st_body, APM_ORA_REPORT_SESSION_SID, p_st_sess->p_db_sid) != FR_SUCC)
        goto error;
    if ((p_st_sess->st_logined_timestamp.tv_sec != 0L || p_st_sess->st_logined_timestamp.tv_usec != 0L) &&
            frreport_body_l7_add_timeval(p_st_body, APM_REPORT_KEY_SESSION_LOGIN_TIMESTAMP, &(p_st_sess->st_logined_timestamp)) != FR_SUCC)
        goto error;

    return p_st_body;
error:
    frreport_body_free(&p_st_body);
    return NULL;
}


/*******************************************************************************
*  FUNC     :  上报statement的请求信息
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  st_timestamp_first                   (分片包时，第一个分片包的时间；不为分片包时与st_timestamp_last相同)
*           :  *p_st_hash_report                    (数据上报)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_report_stmt_req(Conntrack *p_st_conn
                        , L7session_ora *p_st_sess
                        , Sql_statement *p_st_stmt
                        , Frhash_header *p_st_hash_report)
{
    ORA_PRINT_INFO("ora_report_stmt_req\n");
    Frreport_body_data *p_st_body = NULL;

    if ((p_st_body = __ora_new_report_body(p_st_conn, p_st_sess)) == NULL)
        goto error;

    if (frdb_report_req(p_st_conn, p_st_hash_report, p_st_stmt, FRDB_LAST, 0L, &p_st_body) != FR_SUCC)
        goto error;

    return FR_SUCC;
error:
    frreport_body_free(&p_st_body);
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  上报statement的响应信息
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  st_timestamp_first                   (分片包时，第一个分片包的时间；不为分片包时与st_timestamp_last相同)
*           :  *p_st_hash_report                    (数据上报)
*           :  i_last_resultset                     (是否上报最后一个resultset)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_report_stmt_resp(Conntrack *p_st_conn
                        , L7session_ora *p_st_sess
                        , Sql_statement *p_st_stmt
                        , Frhash_header *p_st_hash_report
                        , int i_last_resultset)
{
    ORA_PRINT_INFO("ora_report_stmt_resp\n");
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_resp_ora *p_st_resp = p_st_session_private->p_st_resp;
    Frreport_body_data *p_st_body = NULL;

    Sql_resultset *p_st_rs = NULL;
    Frlist_node *p_st_node = NULL;

    if (p_st_stmt->p_sql == NULL)
    {
        ORA_PRINT_EMERG("Has no sql data, do not report response\n");
        goto success;
    }
    else
        ORA_PRINT_DBG("report stmt of cursor:[%ld] and sql:[%s]\n", p_st_stmt->l_cursor_id, p_st_stmt->p_sql);

    if (i_last_resultset == FR_YES)
    {
        if ((p_st_rs = frdb_get_last_resultset(p_st_stmt)) == NULL)
            goto error;

        if (p_st_resp->l_response_code >= 0)
        {
            if ((p_st_body = __ora_new_report_body(p_st_conn, p_st_sess)) == NULL)
                goto error;
            if (frdb_report_resp2(p_st_conn, p_st_hash_report, p_st_stmt, p_st_rs, p_st_resp->l_response_code,
                                  p_st_resp->p_response_codestring, p_st_resp->p_response_error_mesg, &p_st_body) != FR_SUCC)
                goto error;
        }

        frdb_init_resultset(p_st_rs, frct_seq_increase(p_st_conn));
    }
    else
    {
        p_st_node = FRLIST_FIRST_NODE(&(p_st_stmt->st_resultset_list));
        while (p_st_node)
        {
            p_st_rs = (Sql_resultset *) FRLIST_GET_NODE_DATA(p_st_node);

            if (p_st_resp->l_response_code >= 0)
            {
                if ((p_st_body = __ora_new_report_body(p_st_conn, p_st_sess)) == NULL)
                    goto error;
                if (frdb_report_resp2(p_st_conn, p_st_hash_report, p_st_stmt, p_st_rs, p_st_resp->l_response_code,
                                      p_st_resp->p_response_codestring, p_st_resp->p_response_error_mesg, &p_st_body) != FR_SUCC)
                    goto error;
            }

            p_st_node = FRLIST_NEXT_NODE(p_st_node);
        }
    }

success:
    return FR_SUCC;
error:
    frreport_body_free(&p_st_body);
    return FR_FAIL;
}


/*******************************************************************************
*  FUNC     :  设置需要下个分片包的标识
*  ARGS     :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_packet_need_next_packet(L7_ora_packet *p_st_ora_packet)
{
    if (p_st_ora_packet->i_is_request == APM_ORA_FLAG_UNSET)
    {
        ORA_PRINT_EMERG("ora_packet_need_next_packet p_st_ora_packet->i_is_request is APM_ORA_FLAG_UNSET\n");
        ORA_FRLOG_ERROR("ora_packet_need_next_packet p_st_ora_packet->i_is_request is APM_ORA_FLAG_UNSET");
        return;
    }
    ORA_PRINT_WARN("NEED NEXT PACKET!\n");
    if (p_st_ora_packet->i_is_request == FR_YES)
        p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_NEED_NEXT_REQ_PACKET;
    else
        p_st_ora_packet->fragment_state = APM_ORA_FRAGMENT_NEED_NEXT_RESP_PACKET;
}

/*******************************************************************************
*  FUNC     :  判断是否处于分片包状态
*  ARGS     :  *p_st_ora_packet                     (Oracle数据包)
*  RTN      :  0                                    (FR_NO)
*              1                                    (FR_YES)
*  NOTE     :
*******************************************************************************/
int ora_packet_is_in_fragment(L7_ora_packet *p_st_ora_packet)
{
    if (p_st_ora_packet == NULL)
        return FR_NO;

    return (p_st_ora_packet->fragment_state == APM_ORA_FRAGMENT_NEED_NEXT_REQ_PACKET
            || p_st_ora_packet->fragment_state == APM_ORA_FRAGMENT_NEED_NEXT_RESP_PACKET) ? FR_YES : FR_NO;
}

/*******************************************************************************
*  FUNC     :  检查是否是sql语句
*  ARGS     :  *p_sql                               (sql语句)
*           :  i_sql_len                            (sql语句长度)
*  RTN      :  0                                    (FR_NO)
*              1                                    (FR_YES)
*  NOTE     :
*******************************************************************************/
int ora_is_sql(char *p_sql
              , int i_sql_len)
{
    if (p_sql == NULL || i_sql_len <= 5)
        return FR_FAIL;
    if (strncasecmp(p_sql, "select ", 7) == 0 ||
        strncasecmp(p_sql, "insert ", 7) == 0 ||
        strncasecmp(p_sql, "update ", 7) == 0 ||
        strncasecmp(p_sql, "delete ", 7) == 0 ||
        strncasecmp(p_sql, "merge ", 6) == 0 ||
        strncasecmp(p_sql, "create ", 7) == 0 ||
        strncasecmp(p_sql, "drop ", 5) == 0 ||
        strncasecmp(p_sql, "grant ", 6) == 0 ||
        strncasecmp(p_sql, "commit", 6) == 0 ||
        strncasecmp(p_sql, "rollback", 8) == 0 ||
        strncasecmp(p_sql, "alter ", 6) == 0 ||
        strncasecmp(p_sql, "desc ", 5) == 0 ||
        strncasecmp(p_sql, "show ", 5) == 0 ||
        strncasecmp(p_sql, "truncate ", 9) == 0 ||
        strncasecmp(p_sql, "revoke ", 7) == 0 ||
        strncasecmp(p_sql, "begin ", 6) == 0)
        return FR_SUCC;
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  检查是不是select语句
*  ARGS     :  *p_sql                               (sql语句)
*           :  i_sql_len                            (sql语句长度)
*  RTN      :  0                                    (FR_NO)
*              1                                    (FR_YES)
*  NOTE     :
*******************************************************************************/
int ora_is_sql_select(char *p_sql
                    , int i_sql_len)
{
    if (p_sql == NULL || i_sql_len <= 7)
        return FR_FAIL;
    if (strncasecmp(p_sql, "select ", 7) == 0)
        return FR_SUCC;
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  检查是不是DML语句(delete/insert/update/merge)
*  ARGS     :  *p_sql                               (sql语句)
*           :  i_sql_len                            (sql语句长度)
*  RTN      :  0                                    (FR_NO)
*              1                                    (FR_YES)
*  NOTE     :
*******************************************************************************/
int ora_is_sql_dml(char *p_sql
                , int i_sql_len)
{
    if (p_sql == NULL || i_sql_len <= 6)
        return FR_FAIL;
    if (strncasecmp(p_sql, "insert ", 7) == 0 ||
        strncasecmp(p_sql, "update ", 7) == 0 ||
        strncasecmp(p_sql, "delete ", 7) == 0 ||
        strncasecmp(p_sql, "merge ", 6) == 0)
        return FR_SUCC;
    return FR_FAIL;
}

/*******************************************************************************
*  FUNC     :  保存oracle的服务器信息
*  ARGS     :  *p_st_sess                                 (L7session_oracle结构体)
*              *p_st_packet                               (协议分析入力数据)
*  RTN      :
*  NOTE     :
*******************************************************************************/
void ora_service_list_add(L7session_ora *p_st_sess
                         , Apm_packet *p_st_packet)
{
    // 10g以上(包含)的版本没有使用到redirect策略，可以保存服务器信息
    if (p_st_sess->s_version_number >= 10000)
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0);
}

/*******************************************************************************
*  FUNC     :  Frdata_field释放
*  ARGS     :  pp_st_field(Frdata_field)
*  RTN      :  void
*  NOTE     :
*******************************************************************************/
void ora_frdata_free(Frdata_field **pp_st_field)
{
    if (pp_st_field == NULL || *pp_st_field == NULL)
        return;

    ora_free((void **) &(*pp_st_field)->p_field_name);
    ora_free((void **) &(*pp_st_field)->p_field_value);
    ora_free((void **) pp_st_field);
    return;
}

/**
 * 删除SQL中的注释语
 */
void ora_sql_delete_comments(char **pp_sql)
{
    char *p_sql = NULL;
    char *p_sql_modified = NULL;
    unsigned int ui_offset = 0;
    unsigned long ul_sql_modified_len = 0;
    char *p_tmp = NULL;

    if (pp_sql == NULL || *pp_sql == NULL || **pp_sql == '\0')
        return;

    p_sql = *pp_sql;

    ul_sql_modified_len = strlen(p_sql);

    if ((p_sql_modified = (char *) frmalloc(ul_sql_modified_len + 1)) == NULL)
    {
        ORA_MALLOCK_ERR;
        return;
    }
    memset(p_sql_modified, 0x00, ul_sql_modified_len + 1);

    while (*p_sql)
    {
        switch (*p_sql)
        {
            case ' ':
            case '\t':
            case '\r':
            case '\n':
                p_sql_modified[ui_offset++] = *p_sql;
                p_sql++;
                break;
            case '/':
                if (*(p_sql + 1) == '*') // 找到多行注释符 起始符 /*
                {
                    p_sql += 2;
                    if ((p_tmp = strstr(p_sql, "*/")) != NULL) // 找到多行注释符 结束符 */
                        p_sql = p_tmp + 2;
                    else
                    {
                        ora_free((void **) &p_sql_modified);
                        return;
                    }
                }
                else
                {
                    p_sql_modified[ui_offset++] = *p_sql;
                    p_sql++;
                }
                break;
            case '\'':
                p_sql_modified[ui_offset++] = *p_sql;
                p_sql++;
                while (*p_sql)
                {
                    p_sql_modified[ui_offset++] = *p_sql;
                    if (*p_sql == '\'' && *(p_sql + 1) != '\'')
                    {
                        p_sql++;
                        break;
                    }
                    p_sql++;
                }
                break;
            case '-':
                if (*(p_sql + 1) == '-') // 找到单行注释符 --
                {
                    p_sql += 2;
                    while (*p_sql)
                    {
                        if (*p_sql == '\r')
                        {
                            if (*(p_sql + 1) == '\n')
                                p_sql += 2;
                            else
                                p_sql++;
                            break;
                        }
                        else if (*p_sql == '\n')
                        {
                            p_sql++;
                            break;
                        }
                        p_sql++;
                    }
                }
                else
                {
                    p_sql_modified[ui_offset++] = *p_sql;
                    p_sql++;
                }
                break;
            default:
                p_sql_modified[ui_offset++] = *p_sql;
                p_sql++;
                ;
        }
    }

    ora_free((void **) pp_sql);
    *pp_sql = p_sql_modified;

    return;
}
